home *** CD-ROM | disk | FTP | other *** search
/ Aminet 5 / Aminet 5 - March 1995.iso / Aminet / util / libs / type1beta5.lha / type1 / src / scanfont.c < prev    next >
C/C++ Source or Header  |  1995-01-08  |  42KB  |  1,628 lines

  1. /* $XConsortium: scanfont.c,v 1.10 94/02/06 16:23:17 gildea Exp $ */
  2. /* Copyright International Business Machines,Corp. 1991
  3.  * All Rights Reserved
  4.  *
  5.  * License to use, copy, modify, and distribute this software
  6.  * and its documentation for any purpose and without fee is
  7.  * hereby granted, provided that the above copyright notice
  8.  * appear in all copies and that both that copyright notice and
  9.  * this permission notice appear in supporting documentation,
  10.  * and that the name of IBM not be used in advertising or
  11.  * publicity pertaining to distribution of the software without
  12.  * specific, written prior permission.
  13.  *
  14.  * IBM PROVIDES THIS SOFTWARE "AS IS", WITHOUT ANY WARRANTIES
  15.  * OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT
  16.  * LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT OF
  18.  * THIRD PARTY RIGHTS.  THE ENTIRE RISK AS TO THE QUALITY AND
  19.  * PERFORMANCE OF THE SOFTWARE, INCLUDING ANY DUTY TO SUPPORT
  20.  * OR MAINTAIN, BELONGS TO THE LICENSEE.  SHOULD ANY PORTION OF
  21.  * THE SOFTWARE PROVE DEFECTIVE, THE LICENSEE (NOT IBM) ASSUMES
  22.  * THE ENTIRE COST OF ALL SERVICING, REPAIR AND CORRECTION.  IN
  23.  * NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  24.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
  25.  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
  26.  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  27.  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  28.  * SOFTWARE.
  29.  */
  30. /* Author: Katherine A. Hitchcock    IBM Almaden Research Laboratory */
  31.  
  32. #ifndef T1GST
  33. #include "global.h"
  34. #endif
  35.  
  36. static int rc;
  37. static boolean InPrivateDict;
  38. static boolean WantFontInfo;
  39. static boolean TwoSubrs;
  40. static psobj inputFile;
  41. static psobj filterFile;
  42. static psobj *inputP;
  43.  
  44. /**********************************************************************/
  45. /*   Init_BuiltInEncoding()                                           */
  46. /*                                                                    */
  47. /*     Initializes the StandardEncoding and ISOLatin1Encoding vector. */
  48. /*                                                                    */
  49. /**********************************************************************/
  50. typedef struct            /* Builtin Standard Encoding */
  51. {
  52.     int index;
  53.     char *name;
  54. }
  55. EncodingTable;
  56.  
  57. const static EncodingTable StdEnc[] =
  58. {
  59.     040, "space",
  60.     041, "exclam",
  61.     042, "quotedbl",
  62.     043, "numbersign",
  63.     044, "dollar",
  64.     045, "percent",
  65.     046, "ampersand",
  66.     047, "quoteright",
  67.     050, "parenleft",
  68.     051, "parenright",
  69.     052, "asterisk",
  70.     053, "plus",
  71.     054, "comma",
  72.     055, "hyphen",
  73.     056, "period",
  74.     057, "slash",
  75.     060, "zero",
  76.     061, "one",
  77.     062, "two",
  78.     063, "three",
  79.     064, "four",
  80.     065, "five",
  81.     066, "six",
  82.     067, "seven",
  83.     070, "eight",
  84.     071, "nine",
  85.     072, "colon",
  86.     073, "semicolon",
  87.     074, "less",
  88.     075, "equal",
  89.     076, "greater",
  90.     077, "question",
  91.     0100, "at",
  92.     0101, "A",
  93.     0102, "B",
  94.     0103, "C",
  95.     0104, "D",
  96.     0105, "E",
  97.     0106, "F",
  98.     0107, "G",
  99.     0110, "H",
  100.     0111, "I",
  101.     0112, "J",
  102.     0113, "K",
  103.     0114, "L",
  104.     0115, "M",
  105.     0116, "N",
  106.     0117, "O",
  107.     0120, "P",
  108.     0121, "Q",
  109.     0122, "R",
  110.     0123, "S",
  111.     0124, "T",
  112.     0125, "U",
  113.     0126, "V",
  114.     0127, "W",
  115.     0130, "X",
  116.     0131, "Y",
  117.     0132, "Z",
  118.     0133, "bracketleft",
  119.     0134, "backslash",
  120.     0135, "bracketright",
  121.     0136, "asciicircum",
  122.     0137, "underscore",
  123.     0140, "quoteleft",
  124.     0141, "a",
  125.     0142, "b",
  126.     0143, "c",
  127.     0144, "d",
  128.     0145, "e",
  129.     0146, "f",
  130.     0147, "g",
  131.     0150, "h",
  132.     0151, "i",
  133.     0152, "j",
  134.     0153, "k",
  135.     0154, "l",
  136.     0155, "m",
  137.     0156, "n",
  138.     0157, "o",
  139.     0160, "p",
  140.     0161, "q",
  141.     0162, "r",
  142.     0163, "s",
  143.     0164, "t",
  144.     0165, "u",
  145.     0166, "v",
  146.     0167, "w",
  147.     0170, "x",
  148.     0171, "y",
  149.     0172, "z",
  150.     0173, "braceleft",
  151.     0174, "bar",
  152.     0175, "braceright",
  153.     0176, "asciitilde",
  154.     0241, "exclamdown",
  155.     0242, "cent",
  156.     0243, "sterling",
  157.     0244, "fraction",
  158.     0245, "yen",
  159.     0246, "florin",
  160.     0247, "section",
  161.     0250, "currency",
  162.     0251, "quotesingle",
  163.     0252, "quotedblleft",
  164.     0253, "guillemotleft",
  165.     0254, "guilsinglleft",
  166.     0255, "guilsinglright",
  167.     0256, "fi",
  168.     0257, "fl",
  169.     0261, "endash",
  170.     0262, "dagger",
  171.     0263, "daggerdbl",
  172.     0264, "periodcentered",
  173.     0266, "paragraph",
  174.     0267, "bullet",
  175.     0270, "quotesinglbase",
  176.     0271, "quotedblbase",
  177.     0272, "quotedblright",
  178.     0273, "guillemotright",
  179.     0274, "ellipsis",
  180.     0275, "perthousand",
  181.     0277, "questiondown",
  182.     0301, "grave",
  183.     0302, "acute",
  184.     0303, "circumflex",
  185.     0304, "tilde",
  186.     0305, "macron",
  187.     0306, "breve",
  188.     0307, "dotaccent",
  189.     0310, "dieresis",
  190.     0312, "ring",
  191.     0313, "cedilla",
  192.     0315, "hungarumlaut",
  193.     0316, "ogonek",
  194.     0317, "caron",
  195.     0320, "emdash",
  196.     0341, "AE",
  197.     0343, "ordfeminine",
  198.     0350, "Lslash",
  199.     0351, "Oslash",
  200.     0352, "OE",
  201.     0353, "ordmasculine",
  202.     0361, "ae",
  203.     0365, "dotlessi",
  204.     0370, "lslash",
  205.     0371, "oslash",
  206.     0372, "oe",
  207.     0373, "germandbls",
  208.     0, 0
  209. };
  210.  
  211. const static EncodingTable ISO8859Enc[] =
  212. {
  213.     32, "space",
  214.     33, "exclam",
  215.     34, "quotedbl",
  216.     35, "numbersign",
  217.     36, "dollar",
  218.     37, "percent",
  219.     38, "ampersand",
  220.     39, "quoteright",
  221.     40, "parenleft",
  222.     41, "parenright",
  223.     42, "asterisk",
  224.     43, "plus",
  225.     44, "comma",
  226.     45, "minus",
  227.     46, "period",
  228.     47, "slash",
  229.     48, "zero",
  230.     49, "one",
  231.     50, "two",
  232.     51, "three",
  233.     52, "four",
  234.     53, "five",
  235.     54, "six",
  236.     55, "seven",
  237.     56, "eight",
  238.     57, "nine",
  239.     58, "colon",
  240.     59, "semicolon",
  241.     60, "less",
  242.     61, "equal",
  243.     62, "greater",
  244.     63, "question",
  245.     64, "at",
  246.     65, "A",
  247.     66, "B",
  248.     67, "C",
  249.     68, "D",
  250.     69, "E",
  251.     70, "F",
  252.     71, "G",
  253.     72, "H",
  254.     73, "I",
  255.     74, "J",
  256.     75, "K",
  257.     76, "L",
  258.     77, "M",
  259.     78, "N",
  260.     79, "O",
  261.     80, "P",
  262.     81, "Q",
  263.     82, "R",
  264.     83, "S",
  265.     84, "T",
  266.     85, "U",
  267.     86, "V",
  268.     87, "W",
  269.     88, "X",
  270.     89, "Y",
  271.     90, "Z",
  272.     91, "bracketleft",
  273.     92, "backslash",
  274.     93, "bracketright",
  275.     94, "asciicircum",
  276.     95, "underscore",
  277.     96, "quoteleft",
  278.     97, "a",
  279.     98, "b",
  280.     99, "c",
  281.     100, "d",
  282.     101, "e",
  283.     102, "f",
  284.     103, "g",
  285.     104, "h",
  286.     105, "i",
  287.     106, "j",
  288.     107, "k",
  289.     108, "l",
  290.     109, "m",
  291.     110, "n",
  292.     111, "o",
  293.     112, "p",
  294.     113, "q",
  295.     114, "r",
  296.     115, "s",
  297.     116, "t",
  298.     117, "u",
  299.     118, "v",
  300.     119, "w",
  301.     120, "x",
  302.     121, "y",
  303.     122, "z",
  304.     123, "braceleft",
  305.     124, "bar",
  306.     125, "braceright",
  307.     126, "asciitilde",
  308.     161, "exclamdown",
  309.     162, "cent",
  310.     163, "sterling",
  311.     164, "currency",
  312.     165, "yen",
  313.     166, "brokenbar",
  314.     167, "section",
  315.     168, "dieresis",
  316.     169, "copyright",
  317.     170, "ordfeminine",
  318.     171, "guillemotleft",
  319.     172, "logicalnot",
  320.     173, "hyphen",
  321.     174, "registered",
  322.     175, "macron",
  323.     176, "degree",
  324.     177, "plusminus",
  325.     178, "twosuperior",
  326.     179, "threesuperior",
  327.     180, "acute",
  328.     181, "mu",
  329.     182, "paragraph",
  330.     183, "periodcentered",
  331.     184, "cedilla",
  332.     185, "onesuperior",
  333.     186, "ordmasculine",
  334.     187, "guillemotright",
  335.     188, "onequarter",
  336.     189, "onehalf",
  337.     190, "threequarters",
  338.     191, "questiondown",
  339.     192, "Agrave",
  340.     193, "Aacute",
  341.     194, "Acircumflex",
  342.     195, "Atilde",
  343.     196, "Adieresis",
  344.     197, "Aring",
  345.     198, "AE",
  346.     199, "Ccedilla",
  347.     200, "Egrave",
  348.     201, "Eacute",
  349.     202, "Ecircumflex",
  350.     203, "Edieresis",
  351.     204, "Igrave",
  352.     205, "Iacute",
  353.     206, "Icircumflex",
  354.     207, "Idieresis",
  355.     208, "Eth",
  356.     209, "Ntilde",
  357.     210, "Ograve",
  358.     211, "Oacute",
  359.     212, "Ocircumflex",
  360.     213, "Otilde",
  361.     214, "Odieresis",
  362.     215, "multiply",
  363.     216, "Oslash",
  364.     217, "Ugrave",
  365.     218, "Uacute",
  366.     219, "Ucircumflex",
  367.     220, "Udieresis",
  368.     221, "Yacute",
  369.     222, "Thorn",
  370.     223, "germandbls",
  371.     224, "agrave",
  372.     225, "aacute",
  373.     226, "acircumflex",
  374.     227, "atilde",
  375.     228, "adieresis",
  376.     229, "aring",
  377.     230, "ae",
  378.     231, "ccedilla",
  379.     232, "egrave",
  380.     233, "eacute",
  381.     234, "ecircumflex",
  382.     235, "edieresis",
  383.     236, "igrave",
  384.     237, "iacute",
  385.     238, "icircumflex",
  386.     239, "idieresis",
  387.     240, "eth",
  388.     241, "ntilde",
  389.     242, "ograve",
  390.     243, "oacute",
  391.     244, "ocircumflex",
  392.     245, "otilde",
  393.     246, "odieresis",
  394.     247, "divide",
  395.     248, "oslash",
  396.     249, "ugrave",
  397.     250, "uacute",
  398.     251, "ucircumflex",
  399.     252, "udieresis",
  400.     253, "yacute",
  401.     254, "thorn",
  402.     255, "ydieresis",
  403.     0, 0
  404. };
  405.  
  406. static psobj *StdEncArrayP = NULL;
  407. psobj *ISOLatin1EncArrayP = NULL;
  408.  
  409. static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable);
  410. static int getNextValue(int valueType);
  411. static int getInt(void);
  412. static int getEncoding(psobj *arrayP);
  413. static int getArray(psobj *arrayP);
  414. static int getName(char *nameP);
  415. static int getNbytes(int N);
  416. static int getLiteralName(psobj *nameObjP);
  417. static int BuildSubrs(psfont *FontP);
  418. static int BuildCharStrings(psfont *FontP);
  419. static int BuildFontInfo(psfont *fontP);
  420. static int BuildPrivate(psfont *fontP);
  421. static int GetType1Blues(psfont *fontP);
  422. static int FindDictValue(psdict *dictP);
  423.  
  424.  
  425. static psobj *MakeEncodingArrayP(const EncodingTable *encodingTable)
  426. {
  427.     int i;
  428.     psobj *encodingArrayP;
  429.  
  430.     encodingArrayP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  431.     if (!encodingArrayP)
  432.         return NULL;
  433.  
  434.     /* initialize everything to .notdef */
  435.     for (i = 0; i < 256; i++)
  436.         objFormatName(&(encodingArrayP[i]), 7, ".notdef");
  437.  
  438.     for (i = 0; encodingTable[i].name; i++)
  439.     {
  440.         objFormatName(&(encodingArrayP[encodingTable[i].index]),
  441.                   strlen(encodingTable[i].name),
  442.                   encodingTable[i].name);
  443.     }
  444.  
  445.     return (encodingArrayP);
  446. }
  447.  
  448. boolean Init_BuiltInEncoding(void)
  449. {
  450.     StdEncArrayP = MakeEncodingArrayP(StdEnc);
  451.     ISOLatin1EncArrayP = MakeEncodingArrayP(ISO8859Enc);
  452.     return (StdEncArrayP && ISOLatin1EncArrayP);
  453. }
  454.  
  455. /********************************************************************/
  456. /***================================================================***/
  457. static int getNextValue(int valueType)
  458. {
  459.     scan_token(inputP);
  460.     if (tokenType != valueType)
  461.     {
  462.         return (SCAN_ERROR);
  463.     }
  464.     return (SCAN_OK);
  465.  
  466. }
  467. /***================================================================***/
  468. /*  This routine will set the global rc if there is an error          */
  469. /***================================================================***/
  470. static int getInt(void)
  471. {
  472.     scan_token(inputP);
  473.     if (tokenType != TOKEN_INTEGER)
  474.     {
  475.         rc = SCAN_ERROR;
  476.         return (0);
  477.     }
  478.     else
  479.     {
  480.         return (tokenValue.integer);
  481.     }
  482.  
  483. }
  484. /***================================================================***/
  485. /*
  486.  * See Sec 10.3 of ``Adobe Type 1 Font Format'' v1.1,
  487.  * for parsing Encoding.
  488.  */
  489. static int getEncoding(psobj *arrayP)
  490. {
  491.  
  492.     scan_token(inputP);
  493.     if ((tokenType == TOKEN_NAME)
  494.         &&
  495.         (((tokenLength == 16) && (!strncmp(tokenStartP, "StandardEncoding", 16))) ||
  496.          (((tokenLength == 17) && (!strncmp(tokenStartP, "ISOLatin1Encoding", 17))))))
  497.     {
  498.         /* Adobe Standard Encoding */
  499.  
  500.         if (tokenLength == 16)
  501.             arrayP->data.valueP = (char *)StdEncArrayP;
  502.         else
  503.             arrayP->data.valueP = (char *)ISOLatin1EncArrayP;
  504.  
  505.         arrayP->len = 256;
  506.         return (SCAN_OK);
  507.     }
  508.     else if ((tokenType == TOKEN_LEFT_BRACE) ||
  509.          (tokenType == TOKEN_LEFT_BRACKET))
  510.     {
  511.         /* Array of literal names */
  512.  
  513.         psobj *objP;
  514.         int i;
  515.  
  516.         objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  517.         if (!(objP))
  518.             return (SCAN_OUT_OF_MEMORY);
  519.  
  520.         arrayP->data.valueP = (char *)objP;
  521.         arrayP->len = 256;
  522.  
  523.         for (i = 0; i < 256; i++, objP++)
  524.         {
  525.             scan_token(inputP);
  526.  
  527.             if (tokenType != TOKEN_LITERAL_NAME)
  528.                 return (SCAN_ERROR);
  529.  
  530.             if (!(vm_alloc(tokenLength)))
  531.                 return (SCAN_OUT_OF_MEMORY);
  532.  
  533.             objFormatName(objP, tokenLength, tokenStartP);
  534.         }
  535.  
  536.         scan_token(inputP);
  537.         if ((tokenType == TOKEN_RIGHT_BRACE) ||
  538.             (tokenType == TOKEN_RIGHT_BRACKET))
  539.             return (SCAN_OK);
  540.     }
  541.     else
  542.     {
  543.         /* Must be sequences of ``dup <index> <charactername> put" */
  544.  
  545.         psobj *objP;
  546.         int i;
  547.  
  548.         objP = (psobj *) vm_alloc(256 * (sizeof(psobj)));
  549.         if (!(objP))
  550.             return (SCAN_OUT_OF_MEMORY);
  551.  
  552.         arrayP->data.valueP = (char *)objP;
  553.         arrayP->len = 256;
  554.  
  555.         for (i = 0; i < 256; i++)
  556.             objFormatName(objP + i, 7, ".notdef");
  557.  
  558.         while (TRUE)
  559.         {
  560.             scan_token(inputP);
  561.  
  562.             switch (tokenType)
  563.             {
  564.             case TOKEN_NAME:
  565.                 if (tokenLength == 3)
  566.                 {
  567.                     if (strncmp(tokenStartP, "dup", 3) == 0)
  568.                     {
  569.                         /* get <index> */
  570.                         scan_token(inputP);
  571.                         if (tokenType != TOKEN_INTEGER ||
  572.                             tokenValue.integer < 0 ||
  573.                             tokenValue.integer > 255)
  574.                             return (SCAN_ERROR);
  575.                         i = tokenValue.integer;
  576.  
  577.                         /* get <characer_name> */
  578.                         scan_token(inputP);
  579.                         if (tokenType != TOKEN_LITERAL_NAME)
  580.                             return (SCAN_ERROR);
  581.  
  582.                         if (!(vm_alloc(tokenLength)))
  583.                             return (SCAN_OUT_OF_MEMORY);
  584.                         objFormatName(objP + i, tokenLength, tokenStartP);
  585.  
  586.                         /* get "put" */
  587.                         scan_token(inputP);
  588.                         if (tokenType != TOKEN_NAME)
  589.                             return (SCAN_ERROR);
  590.                     }
  591.                     else if (strncmp(tokenStartP, "def", 3) == 0)
  592.                         return (SCAN_OK);
  593.                 }
  594.                 break;
  595.             case TOKEN_EOF:
  596.             case TOKEN_NONE:
  597.             case TOKEN_INVALID:
  598.                 return (SCAN_ERROR);
  599.             }
  600.         }
  601.     }
  602.  
  603.     return (SCAN_ERROR);
  604. }
  605. /***================================================================***/
  606. static int getArray(psobj *arrayP)
  607. {
  608.     int N;            /* count the items in the array */
  609.     psobj *objP;
  610.  
  611.  
  612.     scan_token(inputP);
  613.     if ((tokenType != TOKEN_LEFT_BRACE) &&
  614.         (tokenType != TOKEN_LEFT_BRACKET))
  615.     {
  616.         return (SCAN_ERROR);
  617.     }
  618.     /* format the array in memory, save pointer to the beginning */
  619.     arrayP->data.valueP = tokenStartP;
  620.     /* loop, picking up next object, until right BRACE or BRACKET */
  621.     N = 0;
  622.     do
  623.     {
  624.         scan_token(inputP);
  625.         if ((tokenType == TOKEN_RIGHT_BRACE) ||
  626.             (tokenType == TOKEN_RIGHT_BRACKET))
  627.         {
  628.             /* save then number of items in the array */
  629.             arrayP->len = N;
  630.             return (SCAN_OK);
  631.         }
  632.         /* allocate the space for the object */
  633.         objP = (psobj *) vm_alloc(sizeof(psobj));
  634.         if (!(objP))
  635.             return (SCAN_OUT_OF_MEMORY);
  636.  
  637.         /* array is an array of numbers, (real or integer)  */
  638.         if (tokenType == TOKEN_REAL)
  639.         {
  640.             objFormatReal(objP, tokenValue.real);
  641.         }
  642.         else if (tokenType == TOKEN_INTEGER)
  643.         {
  644.             objFormatInteger(objP, tokenValue.integer);
  645.         }
  646.         else
  647.             return (SCAN_ERROR);
  648.         N++;
  649.     }
  650.     while (1 > 0);
  651.     /* NOTREACHED*/
  652. }
  653. /***================================================================***/
  654. static int getName(char *nameP)
  655. {
  656.     do
  657.     {
  658.         scan_token(inputP);
  659.         if (tokenType <= TOKEN_NONE)
  660.         {
  661.             if (tokenTooLong)
  662.                 return (SCAN_OUT_OF_MEMORY);
  663.             return (SCAN_ERROR);
  664.         }
  665.     }
  666.     while ((tokenType != TOKEN_NAME) ||
  667.            (0 != strncmp(tokenStartP, nameP, strlen(nameP))));
  668.     /* found */
  669.     return (SCAN_OK);
  670. }
  671. /***================================================================***/
  672. static int getNbytes(int N)
  673. {
  674.     int I;
  675.  
  676.  
  677.     tokenStartP = vm_next_byte();
  678.     tokenMaxP = tokenStartP + MIN(vm_free_bytes(), MAX_STRING_LEN);
  679.     if (N > vm_free_bytes())
  680.     {
  681.         return (SCAN_OUT_OF_MEMORY);
  682.     }
  683.     I = T1Read(tokenStartP, 1, N, inputP->data.fileP);
  684.     if (I != N)
  685.         return (SCAN_FILE_EOF);
  686.     return (SCAN_OK);
  687. }
  688.  
  689. /***================================================================***/
  690. /*  getLiteralName(nameObjP)                                          */
  691. /*     scan for next literal.                                         */
  692. /*  if we encounter the name 'end' then terminate and say ok.         */
  693. /*    It means that the CharStrings does not have as many characters  */
  694. /*    as the dictionary said it would and that is ok.                 */
  695. /***================================================================***/
  696. static int getLiteralName(psobj *nameObjP)
  697. {
  698.     do
  699.     {
  700.         scan_token(inputP);
  701.         if (tokenType <= TOKEN_NONE)
  702.         {
  703.             if (tokenTooLong)
  704.                 return (SCAN_OUT_OF_MEMORY);
  705.             return (SCAN_ERROR);
  706.         }
  707.         if (tokenType == TOKEN_NAME)
  708.         {
  709.             if (0 == strncmp(tokenStartP, "end", 3))
  710.             {
  711.                 return (SCAN_END);
  712.             }
  713.         }
  714.     }
  715.     while (tokenType != TOKEN_LITERAL_NAME);
  716.     nameObjP->len = tokenLength;
  717.     /* allocate all the names in the CharStrings Structure */
  718.     if (!(vm_alloc(tokenLength)))
  719.         return (SCAN_OUT_OF_MEMORY);
  720.     nameObjP->data.valueP = tokenStartP;
  721.     /* found */
  722.     return (SCAN_OK);
  723. }
  724.  
  725. /***================================================================***/
  726. /*
  727.  *   BuildSubrs routine
  728.  */
  729. /***================================================================***/
  730.  
  731. static int BuildSubrs(psfont *FontP)
  732. {
  733.     int N;            /* number of values in Subrs */
  734.     int I;            /* index into Subrs */
  735.     int i;            /* loop thru  Subrs */
  736.     int J;            /* length of Subrs entry */
  737.     psobj *arrayP;
  738.  
  739.     /* next token should be a positive int */
  740.     /* note: rc is set by getInt. */
  741.     N = getInt();
  742.     if (rc)
  743.         return (rc);
  744.     if (N < 0)
  745.         return (SCAN_ERROR);
  746.     /* if we already have a Subrs, then skip the second one */
  747.     /* The second one is for hiresolution devices.          */
  748.     if (FontP->Subrs.data.arrayP != NULL)
  749.     {
  750.         TwoSubrs = TRUE;
  751.         /* process all the Subrs, but do not update anything */
  752.         /* can not just skip them because of the binary data */
  753.         for (i = 0; i < N; i++)
  754.         {
  755.             /* look for dup */
  756.             rc = getName("dup");
  757.             if (rc)
  758.                 return (rc);
  759.             /* get 2 integers */
  760.             I = getInt();
  761.             if (rc)
  762.                 return (rc);
  763.             J = getInt();
  764.             if (rc)
  765.                 return (rc);
  766.             if ((I < 0) || (J < 0))
  767.                 return (SCAN_ERROR);
  768.             /* get the next token, it should be RD or -|, either is ok */
  769.             rc = getNextValue(TOKEN_NAME);
  770.             if (rc != SCAN_OK)
  771.                 return (rc);
  772.             rc = getNbytes(J);
  773.             if (rc)
  774.                 return (rc);
  775.         }
  776.         return (SCAN_OK);
  777.     }
  778.  
  779.     arrayP = (psobj *) vm_alloc(N * sizeof(psobj));
  780.     if (!(arrayP))
  781.         return (SCAN_OUT_OF_MEMORY);
  782.     FontP->Subrs.len = N;
  783.     FontP->Subrs.data.arrayP = arrayP;
  784.     /* get N values for Subrs */
  785.     for (i = 0; i < N; i++)
  786.     {
  787.         /* look for dup */
  788.         rc = getName("dup");
  789.         if (rc)
  790.             return (rc);
  791.         /* get 2 integers */
  792.         I = getInt();
  793.         if (rc)
  794.             return (rc);
  795.         J = getInt();
  796.         if (rc)
  797.             return (rc);
  798.         if ((I < 0) || (J < 0))
  799.             return (SCAN_ERROR);
  800.         arrayP[I].len = J;
  801.         /* get the next token, it should be RD or -|, either is ok */
  802.         rc = getNextValue(TOKEN_NAME);
  803.         if (rc != SCAN_OK)
  804.             return (rc);
  805.         rc = getNbytes(J);
  806.         if (rc == SCAN_OK)
  807.         {
  808.             arrayP[I].data.valueP = tokenStartP;
  809.             if (!(vm_alloc(J)))
  810.                 return (SCAN_OUT_OF_MEMORY);
  811.         }
  812.         else
  813.             return (rc);
  814.     }
  815.     return (SCAN_OK);
  816.  
  817. }
  818. /***================================================================***/
  819. /***================================================================***/
  820. /*
  821.  *   BuildCharStrings routine
  822.  */
  823. /***================================================================***/
  824.  
  825. static int BuildCharStrings(psfont *FontP)
  826. {
  827.     int N;            /* number of values in CharStrings */
  828.     int i;            /* loop thru  Subrs */
  829.     int J;            /* length of Subrs entry */
  830.     psdict *dictP;
  831.  
  832.     /* next token should be a positive int */
  833.     N = getInt();
  834.     if (rc)
  835.     {
  836.         /* check if file had TwoSubrs, hi resolution stuff is in file*/
  837.         if (TwoSubrs)
  838.         {
  839.             do
  840.             {
  841.                 scan_token(inputP);
  842.                 if (tokenType <= TOKEN_NONE)
  843.                 {
  844.                     if (tokenTooLong)
  845.                         return (SCAN_OUT_OF_MEMORY);
  846.                     return (SCAN_ERROR);
  847.                 }
  848.             }
  849.             while (tokenType != TOKEN_INTEGER);
  850.             N = tokenValue.integer;
  851.         }
  852.         else
  853.             return (rc);    /* if next token was not an Int */
  854.     }
  855.     if (N <= 0)
  856.         return (SCAN_ERROR);
  857.     /* save number of entries in the dictionary */
  858.  
  859.     dictP = (psdict *) vm_alloc((N + 1) * sizeof(psdict));
  860.     if (!(dictP))
  861.         return (SCAN_OUT_OF_MEMORY);
  862.     FontP->CharStringsP = dictP;
  863.     dictP[0].key.len = N;
  864.     /* get N values for CharStrings */
  865.     for (i = 1; i <= N; i++)
  866.     {
  867.         /* look for next literal name  */
  868.         rc = getLiteralName(&(dictP[i].key));
  869.         if (rc)
  870.             return (rc);
  871.         /* get 1 integer */
  872.         J = getInt();
  873.         if (rc)
  874.             return (rc);    /* if next token was not an Int */
  875.         if (J < 0)
  876.             return (SCAN_ERROR);
  877.         dictP[i].value.len = J;
  878.         /* get the next token, it should be RD or -|, either is ok */
  879.         rc = getNextValue(TOKEN_NAME);
  880.         if (rc != SCAN_OK)
  881.             return (rc);
  882.         rc = getNbytes(J);
  883.         if (rc == SCAN_OK)
  884.         {
  885.             dictP[i].value.data.valueP = tokenStartP;
  886.             if (!(vm_alloc(J)))
  887.                 return (SCAN_OUT_OF_MEMORY);
  888.         }
  889.         else
  890.             return (rc);
  891.     }
  892.     return (SCAN_OK);
  893.  
  894. }
  895. /***================================================================***/
  896. /***================================================================***/
  897. /*
  898.  *   BuildFontInfo Dictionary
  899.  */
  900. /***================================================================***/
  901. static int BuildFontInfo(psfont *fontP)
  902. {
  903.     psdict *dictP;
  904.  
  905.     /* allocate the private dictionary */
  906.     dictP = (psdict *) vm_alloc(20 * sizeof(psdict));
  907.     if (!(dictP))
  908.         return (SCAN_OUT_OF_MEMORY);
  909.  
  910.     fontP->fontInfoP = dictP;
  911.     fontP->fontInfoP[0].key.len = 17;    /* number of actual entries */
  912.     objFormatName(&(dictP[FONTNAME].key), 8, "FontName");
  913.     objFormatName(&(dictP[FONTNAME].value), 0, NULL);
  914.     objFormatName(&(dictP[PAINTTYPE].key), 9, "PaintType");
  915.     objFormatInteger(&(dictP[PAINTTYPE].value), 0);
  916.     objFormatName(&(dictP[FONTTYPENUM].key), 8, "FontType");
  917.     objFormatInteger(&(dictP[FONTTYPENUM].value), 0);
  918.     objFormatName(&(dictP[FONTMATRIX].key), 10, "FontMatrix");
  919.     objFormatArray(&(dictP[FONTMATRIX].value), 0, NULL);
  920.     objFormatName(&(dictP[FONTBBOX].key), 8, "FontBBox");
  921.     objFormatArray(&(dictP[FONTBBOX].value), 0, NULL);
  922.     objFormatName(&(dictP[ENCODING].key), 8, "Encoding");
  923.     objFormatEncoding(&(dictP[ENCODING].value), 0, NULL);
  924.     objFormatName(&(dictP[UNIQUEID].key), 8, "UniqueID");
  925.     objFormatInteger(&(dictP[UNIQUEID].value), 0);
  926.     objFormatName(&(dictP[STROKEWIDTH].key), 11, "StrokeWidth");
  927.     objFormatReal(&(dictP[STROKEWIDTH].value), 0.0);
  928.     objFormatName(&(dictP[VERSION].key), 7, "version");
  929.     objFormatString(&(dictP[VERSION].value), 0, NULL);
  930.     objFormatName(&(dictP[NOTICE].key), 6, "Notice");
  931.     objFormatString(&(dictP[NOTICE].value), 0, NULL);
  932.     objFormatName(&(dictP[FULLNAME].key), 8, "FullName");
  933.     objFormatString(&(dictP[FULLNAME].value), 0, NULL);
  934.     objFormatName(&(dictP[FAMILYNAME].key), 10, "FamilyName");
  935.     objFormatString(&(dictP[FAMILYNAME].value), 0, NULL);
  936.     objFormatName(&(dictP[WEIGHT].key), 6, "Weight");
  937.     objFormatString(&(dictP[WEIGHT].value), 0, NULL);
  938.     objFormatName(&(dictP[ITALICANGLE].key), 11, "ItalicAngle");
  939.     objFormatReal(&(dictP[ITALICANGLE].value), 0.0);
  940.     objFormatName(&(dictP[ISFIXEDPITCH].key), 12, "isFixedPitch");
  941.     objFormatBoolean(&(dictP[ISFIXEDPITCH].value), FALSE);
  942.     objFormatName(&(dictP[UNDERLINEPOSITION].key), 17, "UnderlinePosition");
  943.     objFormatReal(&(dictP[UNDERLINEPOSITION].value), 0.0);
  944.     objFormatName(&(dictP[UNDERLINETHICKNESS].key), 18, "UnderlineThickness");
  945.     objFormatReal(&(dictP[UNDERLINETHICKNESS].value), 0.0);
  946.     return (SCAN_OK);
  947. }
  948. /***================================================================***/
  949. /*
  950.  *   BuildPrivate Dictionary
  951.  */
  952. /***================================================================***/
  953. static int BuildPrivate(psfont *fontP)
  954. {
  955.     psdict *Private;
  956.  
  957.     /* allocate the private dictionary */
  958.     Private = (psdict *) vm_alloc(20 * sizeof(psdict));
  959.  
  960.     if (!(Private))
  961.         return (SCAN_OUT_OF_MEMORY);
  962.  
  963.     fontP->Private = Private;
  964.     fontP->Private[0].key.len = 16;    /* number of actual entries */
  965.  
  966.     objFormatName(&(Private[BLUEVALUES].key), 10, "BlueValues");
  967.     objFormatArray(&(Private[BLUEVALUES].value), 0, NULL);
  968.     objFormatName(&(Private[OTHERBLUES].key), 10, "OtherBlues");
  969.     objFormatArray(&(Private[OTHERBLUES].value), 0, NULL);
  970.     objFormatName(&(Private[FAMILYBLUES].key), 11, "FamilyBlues");
  971.     objFormatArray(&(Private[FAMILYBLUES].value), 0, NULL);
  972.     objFormatName(&(Private[FAMILYOTHERBLUES].key), 16, "FamilyOtherBlues");
  973.     objFormatArray(&(Private[FAMILYOTHERBLUES].value), 0, NULL);
  974.     objFormatName(&(Private[BLUESCALE].key), 9, "BlueScale");
  975.     objFormatReal(&(Private[BLUESCALE].value), DEFAULTBLUESCALE);
  976.     objFormatName(&(Private[BLUESHIFT].key), 9, "BlueShift");
  977.     objFormatInteger(&(Private[BLUESHIFT].value), DEFAULTBLUESHIFT);
  978.     objFormatName(&(Private[BLUEFUZZ].key), 8, "BlueFuzz");
  979.     objFormatInteger(&(Private[BLUEFUZZ].value), DEFAULTBLUEFUZZ);
  980.     objFormatName(&(Private[STDHW].key), 5, "StdHW");
  981.     objFormatArray(&(Private[STDHW].value), 0, NULL);
  982.     objFormatName(&(Private[STDVW].key), 5, "StdVW");
  983.     objFormatArray(&(Private[STDVW].value), 0, NULL);
  984.     objFormatName(&(Private[STEMSNAPH].key), 9, "StemSnapH");
  985.     objFormatArray(&(Private[STEMSNAPH].value), 0, NULL);
  986.     objFormatName(&(Private[STEMSNAPV].key), 9, "StemSnapV");
  987.     objFormatArray(&(Private[STEMSNAPV].value), 0, NULL);
  988.     objFormatName(&(Private[FORCEBOLD].key), 9, "ForceBold");
  989.     objFormatBoolean(&(Private[FORCEBOLD].value), DEFAULTFORCEBOLD);
  990.     objFormatName(&(Private[LANGUAGEGROUP].key), 13, "LanguageGroup");
  991.     objFormatInteger(&(Private[LANGUAGEGROUP].value), DEFAULTLANGUAGEGROUP);
  992.     objFormatName(&(Private[LENIV].key), 5, "LenIV");
  993.     objFormatInteger(&(Private[LENIV].value), DEFAULTLENIV);
  994.     objFormatName(&(Private[RNDSTEMUP].key), 9, "RndStemUp");
  995.     objFormatBoolean(&(Private[RNDSTEMUP].value), DEFAULTRNDSTEMUP);
  996.     objFormatName(&(Private[EXPANSIONFACTOR].key), 9, "ExpansionFactor");
  997.     objFormatReal(&(Private[EXPANSIONFACTOR].value),
  998.               DEFAULTEXPANSIONFACTOR);
  999.     return (SCAN_OK);
  1000. }
  1001. /***================================================================***/
  1002. /**********************************************************************/
  1003. /*     GetType1Blues(fontP)                                           */
  1004. /*                                                                    */
  1005. /*   Routine to support font-level hints.                             */
  1006. /*                                                                    */
  1007. /*         Gets all the Blues information from the Private dictionary */
  1008. /*         for the font.                                              */
  1009. /*                                                                    */
  1010. /*                                                                    */
  1011. /**********************************************************************/
  1012. static int GetType1Blues(psfont *fontP)
  1013. {
  1014.     psdict *PrivateDictP;    /* the Private dict relating to hints */
  1015.     struct blues_struct *blues;    /* ptr for the blues struct we will allocate */
  1016.     int i;
  1017.     psobj *HintEntryP;
  1018.  
  1019.  
  1020.  
  1021.     /* get the Private dictionary pointer */
  1022.     PrivateDictP = fontP->Private;
  1023.  
  1024.     /* allocate the memory for the blues structure */
  1025.     blues = (struct blues_struct *)vm_alloc(sizeof(struct blues_struct));
  1026.  
  1027.     if (!blues)
  1028.         return (SCAN_OUT_OF_MEMORY);
  1029.  
  1030.     /* Make fontP's blues ptr point to this newly allocated structure. */
  1031.     fontP->BluesP = blues;
  1032.  
  1033.     /* fill in the BlueValues array */
  1034.     HintEntryP = &(PrivateDictP[BLUEVALUES].value);
  1035.     /* check to see if the entry exists and if it's an array */
  1036.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1037.         blues->numBlueValues = 0;
  1038.     else
  1039.     {
  1040.         /* get the number of values in the array */
  1041.         if (HintEntryP->len > NUMBLUEVALUES)
  1042.         {
  1043.             blues->numBlueValues = NUMBLUEVALUES;
  1044.         }
  1045.         else
  1046.             blues->numBlueValues = HintEntryP->len;
  1047.         for (i = 0; i <= blues->numBlueValues - 1; ++i)
  1048.         {
  1049.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1050.                 blues->BlueValues[i] =
  1051.                     HintEntryP->data.arrayP[i].data.integer;
  1052.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1053.                 blues->BlueValues[i] =
  1054.                     HintEntryP->data.arrayP[i].data.real;
  1055.             else
  1056.                 blues->BlueValues[i] = 0;
  1057.         }
  1058.     }
  1059.  
  1060.     /* fill in the OtherBlues array */
  1061.     HintEntryP = &(PrivateDictP[OTHERBLUES].value);
  1062.     /* check to see if the entry exists and if it's an array */
  1063.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1064.         blues->numOtherBlues = 0;
  1065.     else
  1066.     {
  1067.         /* get the number of values in the array */
  1068.         if (HintEntryP->len > NUMOTHERBLUES)
  1069.         {
  1070.             blues->numOtherBlues = NUMOTHERBLUES;
  1071.         }
  1072.         else
  1073.             blues->numOtherBlues = HintEntryP->len;
  1074.         for (i = 0; i <= blues->numOtherBlues - 1; ++i)
  1075.         {
  1076.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1077.                 blues->OtherBlues[i] =
  1078.                     HintEntryP->data.arrayP[i].data.integer;
  1079.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1080.                 blues->OtherBlues[i] =
  1081.                     HintEntryP->data.arrayP[i].data.real;
  1082.             else
  1083.                 blues->OtherBlues[i] = 0;
  1084.         }
  1085.     }
  1086.  
  1087.     /* fill in the FamilyBlues array */
  1088.     HintEntryP = &(PrivateDictP[FAMILYBLUES].value);
  1089.     /* check to see if the entry exists and if it's an array */
  1090.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1091.         blues->numFamilyBlues = 0;
  1092.     else
  1093.     {
  1094.         /* get the number of values in the array */
  1095.         if (HintEntryP->len > NUMFAMILYBLUES)
  1096.         {
  1097.             blues->numFamilyBlues = NUMFAMILYBLUES;
  1098.         }
  1099.         else
  1100.             blues->numFamilyBlues = HintEntryP->len;
  1101.         for (i = 0; i <= blues->numFamilyBlues - 1; ++i)
  1102.         {
  1103.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1104.                 blues->FamilyBlues[i] =
  1105.                     HintEntryP->data.arrayP[i].data.integer;
  1106.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1107.                 blues->FamilyBlues[i] =
  1108.                     HintEntryP->data.arrayP[i].data.real;
  1109.             else
  1110.                 blues->FamilyBlues[i] = 0;
  1111.         }
  1112.     }
  1113.  
  1114.     /* fill in the FamilyOtherBlues array */
  1115.     HintEntryP = &(PrivateDictP[FAMILYOTHERBLUES].value);
  1116.     /* check to see if the entry exists and if it's an array */
  1117.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1118.         blues->numFamilyOtherBlues = 0;
  1119.     else
  1120.     {
  1121.         /* get the number of values in the array */
  1122.         if (HintEntryP->len > NUMFAMILYOTHERBLUES)
  1123.         {
  1124.             blues->numFamilyOtherBlues = NUMFAMILYOTHERBLUES;
  1125.         }
  1126.         else
  1127.             blues->numFamilyOtherBlues = HintEntryP->len;
  1128.         for (i = 0; i <= blues->numFamilyOtherBlues - 1; ++i)
  1129.         {
  1130.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1131.                 blues->FamilyOtherBlues[i] =
  1132.                     HintEntryP->data.arrayP[i].data.integer;
  1133.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1134.                 blues->FamilyOtherBlues[i] =
  1135.                     HintEntryP->data.arrayP[i].data.real;
  1136.             else
  1137.                 blues->FamilyOtherBlues[i] = 0;
  1138.         }
  1139.     }
  1140.  
  1141.     /* fill in the StemSnapH array */
  1142.     HintEntryP = &(PrivateDictP[STEMSNAPH].value);
  1143.     /* check to see if the entry exists and if it's an array */
  1144.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1145.         blues->numStemSnapH = 0;
  1146.     else
  1147.     {
  1148.         /* get the number of values in the array */
  1149.         if (HintEntryP->len > NUMSTEMSNAPH)
  1150.         {
  1151.             blues->numStemSnapH = NUMSTEMSNAPH;
  1152.         }
  1153.         else
  1154.             blues->numStemSnapH = HintEntryP->len;
  1155.         for (i = 0; i <= blues->numStemSnapH - 1; ++i)
  1156.         {
  1157.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1158.                 blues->StemSnapH[i] =
  1159.                     HintEntryP->data.arrayP[i].data.integer;
  1160.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1161.                 blues->StemSnapH[i] =
  1162.                     HintEntryP->data.arrayP[i].data.real;
  1163.             else
  1164.                 blues->StemSnapH[i] = 0;
  1165.         }
  1166.     }
  1167.  
  1168.     /* fill in the StemSnapV array */
  1169.     HintEntryP = &(PrivateDictP[STEMSNAPV].value);
  1170.     /* check to see if the entry exists and if it's an array */
  1171.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1172.         blues->numStemSnapV = 0;
  1173.     else
  1174.     {
  1175.         /* get the number of values in the array */
  1176.         if (HintEntryP->len > NUMSTEMSNAPV)
  1177.         {
  1178.             blues->numStemSnapV = NUMSTEMSNAPV;
  1179.         }
  1180.         else
  1181.             blues->numStemSnapV = HintEntryP->len;
  1182.         for (i = 0; i <= blues->numStemSnapV - 1; ++i)
  1183.         {
  1184.             if (objPIsInteger(&HintEntryP->data.arrayP[i]))
  1185.                 blues->StemSnapV[i] =
  1186.                     HintEntryP->data.arrayP[i].data.integer;
  1187.             else if (objPIsReal(&HintEntryP->data.arrayP[i]))
  1188.                 blues->StemSnapV[i] =
  1189.                     HintEntryP->data.arrayP[i].data.real;
  1190.             else
  1191.                 blues->StemSnapV[i] = 0;
  1192.         }
  1193.     }
  1194.  
  1195.     /* fill in the StdVW array */
  1196.     HintEntryP = &(PrivateDictP[STDVW].value);
  1197.     /* check to see if the entry exists and if it's an array */
  1198.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1199.         /* a value of zero signifies no entry */
  1200.         blues->StdVW = 0;
  1201.     else
  1202.     {
  1203.         if (HintEntryP->len > NUMSTDVW)
  1204.         {
  1205.         }
  1206.         if (objPIsInteger(&HintEntryP->data.arrayP[0]))
  1207.             blues->StdVW = HintEntryP->data.arrayP[0].data.integer;
  1208.         else if (objPIsReal(&HintEntryP->data.arrayP[0]))
  1209.             blues->StdVW = HintEntryP->data.arrayP[0].data.real;
  1210.         else
  1211.             blues->StdVW = 0;
  1212.     }
  1213.  
  1214.     /* fill in the StdHW array */
  1215.     HintEntryP = &(PrivateDictP[STDHW].value);
  1216.     /* check to see if the entry exists and if it's an array */
  1217.     if (!objPIsArray(HintEntryP) || (HintEntryP->len == 0))
  1218.         /* a value of zero signifies no entry */
  1219.         blues->StdHW = 0;
  1220.     else
  1221.     {
  1222.         if (HintEntryP->len > NUMSTDHW)
  1223.         {
  1224.         }
  1225.         if (objPIsInteger(&HintEntryP->data.arrayP[0]))
  1226.             blues->StdHW = HintEntryP->data.arrayP[0].data.integer;
  1227.         else if (objPIsReal(&HintEntryP->data.arrayP[0]))
  1228.             blues->StdHW = HintEntryP->data.arrayP[0].data.real;
  1229.         else
  1230.             blues->StdHW = 0;
  1231.     }
  1232.  
  1233.  
  1234.     /* get the ptr to the BlueScale entry */
  1235.     HintEntryP = &(PrivateDictP[BLUESCALE].value);
  1236.     /* put the BlueScale in the blues structure */
  1237.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1238.         blues->BlueScale = HintEntryP->data.integer;
  1239.     else if (objPIsReal(HintEntryP))    /* Error? */
  1240.         blues->BlueScale = HintEntryP->data.real;
  1241.     else
  1242.         blues->BlueScale = DEFAULTBLUESCALE;
  1243.  
  1244.     /* get the ptr to the BlueShift entry */
  1245.     HintEntryP = &(PrivateDictP[BLUESHIFT].value);
  1246.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1247.         blues->BlueShift = HintEntryP->data.integer;
  1248.     else if (objPIsReal(HintEntryP))    /* Error? */
  1249.         blues->BlueShift = HintEntryP->data.real;
  1250.     else
  1251.         blues->BlueShift = DEFAULTBLUESHIFT;
  1252.  
  1253.     /* get the ptr to the BlueFuzz entry */
  1254.     HintEntryP = &(PrivateDictP[BLUEFUZZ].value);
  1255.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1256.         blues->BlueFuzz = HintEntryP->data.integer;
  1257.     else if (objPIsReal(HintEntryP))    /* Error? */
  1258.         blues->BlueFuzz = HintEntryP->data.real;
  1259.     else
  1260.         blues->BlueFuzz = DEFAULTBLUEFUZZ;
  1261.  
  1262.     /* get the ptr to the ForceBold entry */
  1263.     HintEntryP = &(PrivateDictP[FORCEBOLD].value);
  1264.     if (objPIsBoolean(HintEntryP))    /* Must be integer! */
  1265.         blues->ForceBold = HintEntryP->data.boolean;
  1266.     else
  1267.         blues->ForceBold = DEFAULTFORCEBOLD;
  1268.  
  1269.     /* get the ptr to the LanguageGroup entry */
  1270.     HintEntryP = &(PrivateDictP[LANGUAGEGROUP].value);
  1271.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1272.         blues->LanguageGroup = HintEntryP->data.integer;
  1273.     else
  1274.         blues->LanguageGroup = DEFAULTLANGUAGEGROUP;
  1275.  
  1276.     /* get the ptr to the RndStemUp entry */
  1277.     HintEntryP = &(PrivateDictP[RNDSTEMUP].value);
  1278.     if (objPIsBoolean(HintEntryP))    /* Must be integer! */
  1279.         blues->RndStemUp = HintEntryP->data.boolean;
  1280.     else
  1281.         blues->RndStemUp = DEFAULTRNDSTEMUP;
  1282.  
  1283.     /* get the ptr to the lenIV entry */
  1284.     HintEntryP = &(PrivateDictP[LENIV].value);
  1285.     if (objPIsInteger(HintEntryP))    /* Must be integer! */
  1286.         blues->lenIV = HintEntryP->data.integer;
  1287.     else
  1288.         blues->lenIV = DEFAULTLENIV;
  1289.  
  1290.     /* get the ptr to the ExpansionFactor entry */
  1291.     HintEntryP = &(PrivateDictP[EXPANSIONFACTOR].value);
  1292.     if (objPIsInteger(HintEntryP))
  1293.         blues->ExpansionFactor = HintEntryP->data.integer;
  1294.     else if (objPIsReal(HintEntryP))
  1295.         blues->ExpansionFactor = HintEntryP->data.real;
  1296.     else
  1297.         blues->ExpansionFactor = DEFAULTEXPANSIONFACTOR;
  1298.     return (SCAN_OK);
  1299. }
  1300. /**********************************************************************/
  1301. /*   GetType1CharString(fontP,code)                                   */
  1302. /*                                                                    */
  1303. /*          Look up code in the standard encoding vector and return   */
  1304. /*          the charstring associated with the character name.        */
  1305. /*                                                                    */
  1306. /*   fontP  is the psfont structure.                                  */
  1307. /*                                                                    */
  1308. /*   Returns a psobj (string)                                         */
  1309. /**********************************************************************/
  1310. psobj *GetType1CharString(psfont *fontP, unsigned char code)
  1311. {
  1312.     int N;            /* the 'Nth' entry in the CharStrings       */
  1313.     psobj *charnameP;    /* points to psobj that is name of character*/
  1314.  
  1315.     psdict *CharStringsDictP;    /* dictionary with char strings     */
  1316.     psobj *theStringP;    /* the definition for the code */
  1317.  
  1318.  
  1319.  
  1320.     if (StdEncArrayP == NULL)
  1321.     {
  1322.         return (NULL);
  1323.     }
  1324.     /* use the code to index into the standard encoding vector  */
  1325.     charnameP = &(StdEncArrayP[code]);
  1326.  
  1327.     /* test if the encoding array points to a name */
  1328.     if (!(objPIsName(charnameP)))
  1329.     {
  1330.         return (NULL);
  1331.     }
  1332.  
  1333.     /* Now that we have the character name out of the standardencoding */
  1334.     /* get the character definition out of the current font */
  1335.     CharStringsDictP = fontP->CharStringsP;
  1336.  
  1337.     /* search the chars string for this charname as key */
  1338.     N = SearchDictName(CharStringsDictP, charnameP);
  1339.     if (N <= 0)
  1340.     {
  1341.         return (NULL);
  1342.     }
  1343.     /* OK, the nth item is the psobj that is the string for this char */
  1344.     theStringP = &(CharStringsDictP[N].value);
  1345.  
  1346.     return (theStringP);
  1347. }
  1348.  
  1349. /***================================================================***/
  1350. /*
  1351.  *   FindDictValue
  1352.  */
  1353. /***================================================================***/
  1354.  
  1355. static int FindDictValue(psdict *dictP)
  1356. {
  1357.     psobj LitName;
  1358.     int N;
  1359.     int V;
  1360.  
  1361.     /* we have just scanned a token and it is a literal name */
  1362.     /* need to check if that name is in Private dictionary */
  1363.     objFormatName(&LitName, tokenLength, tokenStartP);
  1364.     /* is it in the dictP */
  1365.     N = SearchDictName(dictP, &LitName);
  1366.     /* if found */
  1367.     if (N > 0)
  1368.     {
  1369.         /* what type */
  1370.         switch (dictP[N].value.type)
  1371.         {
  1372.         case OBJ_ENCODING:
  1373.             V = getEncoding(&(dictP[N].value));
  1374.             if (V != SCAN_OK)
  1375.                 return (V);
  1376.             break;
  1377.         case OBJ_ARRAY:
  1378.             V = getArray(&(dictP[N].value));
  1379.             if (V != SCAN_OK)
  1380.                 return (V);
  1381.             break;
  1382.         case OBJ_INTEGER:
  1383.             /* next value in integer */
  1384.             dictP[N].value.data.integer = getInt();
  1385.             if (rc)
  1386.                 return (rc);    /* if next token was not an Int */
  1387.             break;
  1388.         case OBJ_REAL:
  1389.             /* next value must be real or int, store as a real */
  1390.             scan_token(inputP);
  1391.             if (tokenType == TOKEN_REAL)
  1392.             {
  1393.                 dictP[N].value.data.real = tokenValue.real;
  1394.             }
  1395.             else if (tokenType == TOKEN_INTEGER)
  1396.             {
  1397.                 dictP[N].value.data.real = tokenValue.integer;
  1398.             }
  1399.             else
  1400.                 return (SCAN_ERROR);
  1401.             break;
  1402.         case OBJ_NAME:
  1403.             V = getNextValue(TOKEN_LITERAL_NAME);
  1404.             if (V != SCAN_OK)
  1405.                 return (V);
  1406.             if (!(vm_alloc(tokenLength+1)))
  1407.                 return (SCAN_OUT_OF_MEMORY);
  1408.             objFormatName(&(dictP[N].value), tokenLength, tokenStartP);
  1409.             break;
  1410.         case OBJ_STRING:
  1411.             V = getNextValue(TOKEN_STRING);
  1412.             if (V != SCAN_OK)
  1413.                 return (V);
  1414.             if (!(vm_alloc(tokenLength)))
  1415.                 return (SCAN_OUT_OF_MEMORY);
  1416.             objFormatString(&(dictP[N].value), tokenLength, tokenStartP);
  1417.             break;
  1418.         case OBJ_BOOLEAN:
  1419.             scan_token(inputP);
  1420.             if (tokenType != TOKEN_NAME)
  1421.             {
  1422.                 return (SCAN_ERROR);
  1423.             }
  1424.             if (0 == strncmp(tokenStartP, "true", 4))
  1425.             {
  1426.                 dictP[N].value.data.boolean = TRUE;
  1427.             }
  1428.             else if (0 == strncmp(tokenStartP, "false", 5))
  1429.             {
  1430.                 dictP[N].value.data.boolean = FALSE;
  1431.             }
  1432.             else
  1433.                 return (SCAN_ERROR);
  1434.             break;
  1435.  
  1436.         default:
  1437.             return (SCAN_ERROR);
  1438.             break;
  1439.         }
  1440.     }
  1441.     /* Name is not in dictionary.  That is ok. */
  1442.     return (SCAN_OK);
  1443.  
  1444. }
  1445. /***================================================================***/
  1446.  
  1447. /*
  1448.  * -------------------------------------------------------------------
  1449.  *  Scan the next token and convert it into an object
  1450.  *  Result is placed on the Operand Stack as next object
  1451.  * -------------------------------------------------------------------
  1452.  */
  1453. int scan_font(psfont *FontP)
  1454. {
  1455.     char filename[128];
  1456.     char filetype[3];
  1457.     F_FILE *fileP;
  1458.     const char *nameP;
  1459.     int namelen;
  1460.     int V;
  1461.     int i;
  1462.     boolean starthex80;
  1463.  
  1464.     starthex80 = FALSE;
  1465.     filetype[0] = 'r';
  1466. //    filetype[1] = 'b';
  1467. //    filetype[2] = '\0';
  1468.     filetype[1] = '\0';
  1469.     /* copy the filename and remove leading or trailing blanks */
  1470.     /* point to name and search for leading blanks */
  1471.     nameP = FontP->FontFileName.data.nameP;
  1472.     namelen = FontP->FontFileName.len;
  1473.     while (nameP[0] == ' ')
  1474.     {
  1475.         nameP++;
  1476.         namelen--;
  1477.     }
  1478.     /* now remove any trailing blanks */
  1479.     while ((namelen > 0) && (nameP[namelen - 1] == ' '))
  1480.     {
  1481.         namelen--;
  1482.     }
  1483.     strncpy(filename, nameP, namelen);
  1484.     filename[namelen] = '\0';
  1485.     /* file name is now constructed */
  1486.     inputFile.data.fileP = NULL;
  1487.     filterFile.data.fileP = NULL;
  1488.  
  1489.     inputP = &inputFile;
  1490.     if (fileP = T1Open(filename, filetype))
  1491.     {
  1492.         /* get the first byte of file */
  1493.         V = T1getc(fileP);
  1494.         /* if file starts with x'80' then skip next 5 bytes */
  1495.         if (V == 0X80)
  1496.         {
  1497.             for (i = 0; i < 5; i++)
  1498.                 T1getc(fileP);
  1499. //                V = T1getc(fileP);
  1500.             starthex80 = TRUE;
  1501.         }
  1502.         else
  1503.             T1ungetc(V, fileP);
  1504.         objFormatFile(inputP, fileP);
  1505.     }
  1506.     else
  1507.     {
  1508.         return (SCAN_FILE_OPEN_ERROR);
  1509.     };
  1510.  
  1511.     WantFontInfo = TRUE;
  1512.     InPrivateDict = FALSE;
  1513.     TwoSubrs = FALSE;
  1514.     rc = BuildFontInfo(FontP);
  1515.     if (rc != 0)
  1516.         return (rc);
  1517.  
  1518.     /* Assume everything will be OK */
  1519.     rc = 0;
  1520.  
  1521.     /* Loop until complete font is read  */
  1522.     do
  1523.     {
  1524.         /* Scan the next token */
  1525.         scan_token(inputP);
  1526.  
  1527.         /* ==> tokenLength, tokenTooLong, tokenType, and tokenValue are */
  1528.         /* now set */
  1529.  
  1530.         switch (tokenType)
  1531.         {
  1532.         case TOKEN_EOF:
  1533.         case TOKEN_NONE:
  1534.         case TOKEN_INVALID:
  1535.             /* in this case we are done */
  1536.             if (tokenTooLong)
  1537.                 return (SCAN_OUT_OF_MEMORY);
  1538.             rc = SCAN_ERROR;
  1539.             break;
  1540.         case TOKEN_LITERAL_NAME:
  1541.             /* Look up the name */
  1542.             tokenStartP[tokenLength] = '\0';
  1543.             if (InPrivateDict)
  1544.             {
  1545.                 if (0 == strncmp(tokenStartP, "Subrs", 5))
  1546.                 {
  1547.                     rc = BuildSubrs(FontP);
  1548.                     break;
  1549.                 }
  1550.                 if (0 == strncmp(tokenStartP, "CharStrings", 11))
  1551.                 {
  1552.                     rc = BuildCharStrings(FontP);
  1553.                     if ((rc == SCAN_OK) || (rc == SCAN_END))
  1554.                     {
  1555.                         T1Close(inputP->data.fileP);
  1556.                         /* Build the Blues Structure */
  1557.                         rc = GetType1Blues(FontP);
  1558.                         /* whatever the return code, return it */
  1559.                         /* all the work is done. This is the normal exit.*/
  1560.                         return (rc);
  1561.                     }
  1562.                     break;
  1563.                 }
  1564. //                rc = FindDictValue(FontP->Private);
  1565.                 FindDictValue(FontP->Private);
  1566.                 /* we are not going to report errors */
  1567.                 /* Sometimes the font file may test a value such as */
  1568.                 /* testing to see if the font is alreadly loaded with */
  1569.                 /* same UniqueID.  We would faile on /UniqueID get  */
  1570.                 /* because we are expecting a int to follow UniqueID*/
  1571.                 /* If the correct object type does not follow a Name*/
  1572.                 /* then we will skip over it without reporting error*/
  1573.                 rc = SCAN_OK;
  1574.                 break;
  1575.             }    /* end of reading Private dictionary */
  1576.             else if (0 == strncmp(tokenStartP, "Private", 7))
  1577.             {
  1578.                 InPrivateDict = TRUE;
  1579.                 rc = BuildPrivate(FontP);
  1580.                 break;
  1581.             }
  1582.             else if (WantFontInfo)
  1583.             {
  1584. //                rc = FindDictValue(FontP->fontInfoP);
  1585.                 FindDictValue(FontP->fontInfoP);
  1586.                 /* we are not going to report errors */
  1587.                 rc = SCAN_OK;
  1588.                 break;
  1589.             }
  1590.             break;
  1591.         case TOKEN_NAME:
  1592.             if (0 == strncmp(tokenStartP, "eexec", 5))
  1593.             {
  1594.                 /* if file started with x'80', check next 5 bytes */
  1595.                 if (starthex80)
  1596.                 {
  1597.                     V = T1getc(fileP);
  1598.                     if (V == 0X80)
  1599.                     {
  1600.                         for (i = 0; i < 5; i++)
  1601.                             T1getc(fileP);
  1602. //                            V = T1getc(fileP);
  1603.                     }
  1604.                     else
  1605.                         T1ungetc(V, fileP);
  1606.                 }
  1607.                 filterFile.data.fileP = inputP->data.fileP;
  1608.                 T1eexec(inputP->data.fileP);
  1609.                 if (filterFile.data.fileP == NULL)
  1610.                 {
  1611.                     T1Close(inputFile.data.fileP);
  1612.                     return (SCAN_FILE_OPEN_ERROR);
  1613.                 }
  1614.                 inputP = &filterFile;
  1615.  
  1616.                 WantFontInfo = FALSE;
  1617.             }
  1618.             break;
  1619.         }
  1620.  
  1621.     }
  1622.     while (rc == 0);
  1623.     T1Close(inputP->data.fileP);
  1624.     if (tokenTooLong)
  1625.         return (SCAN_OUT_OF_MEMORY);
  1626.     return (rc);
  1627. }
  1628.